home *** CD-ROM | disk | FTP | other *** search
- #include <exec/types.h>
- #include <exec/execbase.h>
- #include <exec/nodes.h>
- #include <exec/resident.h>
- #include <exec/errors.h>
- #include <libraries/expansionbase.h>
- #include <libraries/configvars.h>
- #include <devices/trackdisk.h>
- #include <hardware/intbits.h>
-
- /*
- * Set SysBase to a local variable, that loads directly from 4 when it
- * has to be reloaded
- */
- #define BASE_EXT_DECL
- #define BASE_NAME (*(void **)4)
- #include <inline/exec.h>
-
- #include "device.h"
-
- struct int_data {
- struct Task *sig_task;
- long sig_mask;
- long signal;
- volatile ubyte *board;
- };
-
- /*
- * interrupt handlers for the device. You can have "real" interrupts
- * or have those functions poll for the event. You should normally use
- * real interrupts. (besides, the pollin on the 2091 won't work, because
- * I don't have documentation for it:-()
- */
-
- extern ulong read_scsi_reg (volatile ubyte *board, ulong reg_num);
-
- /* only needed, if the code is in assembler.. (no more:-)) */
- extern int int_code ();
-
- void
- install_int_handler (struct scsi_dev *dev)
- {
- #ifdef REAL_INT
- dev->id_sig_task = FindTask(0);
- dev->id_signal = AllocSignal(-1);
- dev->id_sig_mask = 1 << dev->id_signal;
- dev->id_board = (volatile ubyte *)dev->sc_base;
-
- /* has to be in front of hddisk.device or scsi.device
- * this can be reset to 0 when we never again will "overlay" a running
- * device :-))) */
- dev->sc_iv.is_Node.ln_Pri = 30;
- dev->sc_iv.is_Node.ln_Type = NT_INTERRUPT;
- dev->sc_iv.is_Node.ln_Name = SCSI_NAME;
-
- dev->sc_iv.is_Code = (VOID (*))int_code;
- dev->sc_iv.is_Data = (APTR) &dev->id_sig_task;
-
- AddIntServer(INTB_PORTS, &dev->sc_iv);
- #endif
- }
-
- void
- remove_int_handler (struct scsi_dev *dev)
- {
- #ifdef REAL_INT
- RemIntServer(INTB_PORTS, &dev->sc_iv);
- FreeSignal(dev->id_signal);
- #endif
- }
-
- void
- wait_interrupt (struct scsi_dev *dev)
- {
- #ifdef REAL_INT
- Wait (dev->id_sig_mask);
- #else
- while (!(board[A2090_CNTL_LO] & INT_FOLLOW)) ;
- read_scsi_reg (board, WD_SCSI_STATUS);
- #endif
- }
-
- void
- clear_interrupt (struct scsi_dev *dev)
- {
- #ifdef REAL_INT
- SetSignal(0, dev->id_sig_mask);
- #endif
- }
-
- #ifdef REAL_INT
- #ifdef A2090
- static int
- int_code ()
- {
- register struct int_data *id_pass asm("a1");
- register struct int_data *idi = id_pass;
- int i;
-
- if (idi->board[A2090_CNTL_LO] & INT_FOLLOW)
- {
- read_scsi_reg (idi->board, WD_SCSI_STATUS);
- Signal (idi->sig_task, idi->sig_mask);
- /* for (i=0; i<10; i++) *(unsigned short *)0xdff180 = 0; */
- return 1;
- }
- return 0;
- }
- #endif
- #ifdef A2091
- static int
- int_code ()
- {
- register struct int_data *id_pass asm("a1");
- register struct int_data *idi = id_pass; /* id_pass;*/
- int i;
-
- /* for (i=0; i<10; i++) *(unsigned short *)0xdff180 = 0; */
-
- if (idi->board[0x41] & (1 << 4))
- {
- if (idi->board[0x41] & (1 << 5)) *(ushort *)&idi->board[0xe4] = 0;
-
- if (idi->board[0x41] & (1 << 6))
- {
- read_scsi_reg (idi->board, WD_SCSI_STATUS);
-
- if (idi->board[0xa3] & (1 << 5)) idi->board[0xa7] = 0;
- Signal(idi->sig_task, idi->sig_mask);
- }
- return 1;
- }
- return 0;
- }
- #endif
- #endif
-